#include "smallccompiler.h"

/* 词语法分析 */
char ch;                    // 存放当前读取的字符
enum symbol sym;            // 当前的符号
string id;					// 当前ident
int num;                    // 当前number
string a;               	// 临时符号
string word[norw];        	// 保留字
enum symbol wsym[norw];     // 保留字对应的符号值
enum symbol ssym[nssym];    // 单字符的符号值
tablestruct table[txmax];	// 符号表

/* 输入输出 */
string * pin;				// 输入代码字符串
string * pout;				// 输出文件及出错示意
string * ptable;			// 输出符号表
string * pinstr;			// 输出机器指令
string * pres;				// 输出执行结果
string * pstack;            // 输出数据栈
int inoff;					// 输入代码字符串偏移量
int bracecnt;				// 记录花括号数量

/* Error Recovery */
int lineno;					// 记录行号
int err;					// 错误计数器
string emsg[errnum];		// 出错信息表
bool declbegsys[symnum];    // 表示声明开始的符号集合
bool statbegsys[symnum];    // 表示语句开始的符号集合
bool exprbegsys[symnum];	// 表示表达式开始的符号集合
bool factbegsys[symnum];    // 表示因子开始的符号集合
bool boolbegsys[symnum];	// 表示布尔值开始的符号集合

/* 目标代码生成 */
int cx;						// 虚拟机代码指针，取值范围[0, cxmax-1]
instruction code[cxmax];	// 存放虚拟机代码的数组
string mnemonic[fctnum];	// 虚拟机代码指令名称

/* 解释执行 */
int p = 0;					// 指令指针
int b = 1;					// 指令基址
int t = 0;					// 栈顶指针
struct instruction i;		// 存放当前指令
int s[stacksize];			// 栈
int isComplete;             // 标记是否解释完成
int indata;                 // read得到的值

/* Semaphore */
#ifndef DEBUG_USE_ONLY
sem_t readdata;             // read指令需要读数据
sem_t dataready;            // 数据已经读好了
#endif

/**
 * 编译主函数
 * @param pin_      Qt 文本框获取的代码字符串指针
 * @param pout_     输出信息字符串指针
 * @param pinstr_	输出目标代码
 * @param ptable_   输出符号表
 */
void compile(string * pin_, string * pout_, string * pinstr_, string * ptable_){
	/* 初始化编译器输入输出指针 */
	pin = pin_;
	pout = pout_;
	pinstr = pinstr_;
	ptable = ptable_;

	/* 空输入文件，退出 */
    if ( pin->length() == 0 ){
        * pout = "The input file is empty!\n";
		return;
	}

	/* 初始化词语法分析 */
	init();								// 初始化可识别单词符号
	ch = ' ';
    err = inoff = bracecnt = lineno = cx = 0; // isCondition = 0;

	getsym();

	int tx = 0;
	program(0, &tx);

	if ( err == 0 ){
        * pout = "Compilation succeeded!\n";  // 输出提示语句
		listinstr();					// 根据code列表输出目标代码指令
		listtable(tx);					// 输出符号表 ptable
	}else{
		pout->append(to_string(err)+" error(s) in extended smallC program!\n");
    }
    return;
}

/**
 * 初始化可识别单词符号
 */
void init(){
    for ( int i = 0; i < nssym; ++ i ){
        ssym[i] = nul;
    }
    /* 设置单字符符号 */
    ssym['+'] = plussym;
	ssym['-'] = minussym;
	ssym['*'] = times;
	ssym['/'] = slash;
	ssym['='] = assign;
	ssym['('] = lparen;
	ssym[')'] = rparen;
    ssym['{'] = lbrace;
	ssym['}'] = rbrace;
	ssym[':'] = colon;
	ssym[','] = comma;
	ssym[';'] = semicolon;
	ssym['<'] = lss;
    ssym['>'] = gtr;
    ssym['!'] = excla;
	ssym['%'] = percent;

	/* 设置保留字名字 */
	word[0]  = "const";
	word[1]  = "do";
	word[2]  = "else";
	word[3]  = "for";
	word[4]  = "if";
	word[5]  = "int";
	word[6]  = "read";
	word[7]  = "while";
	word[8]  = "write";
	word[9]  = "xor";
	word[10] = "odd";
	word[11] = "bool";
	word[12] = "true";
	word[13] = "false";
	word[14] = "and";
	word[15] = "or";
	word[16] = "not";

	/* 设置保留字符号 */
	wsym[0]  = constsym;	
	wsym[1]  = dosym;
	wsym[2]  = elsesym;
	wsym[3]  = forsym;
    wsym[4]  = ifsym;
	wsym[5]  = intsym;
	wsym[6]  = readsym;
	wsym[7]  = whilesym;
	wsym[8]  = writesym;
	wsym[9]  = xorsym;
	wsym[10] = oddsym;
	wsym[11] = boolsym;
	wsym[12] = truesym;
	wsym[13] = falsesym;
	wsym[14] = andsym;
	wsym[15] = orsym;
	wsym[16] = notsym;

	/* 设置符号集 */
	for ( int i = 0; i < symnum; ++ i ){
		declbegsys[i] = false;
		statbegsys[i] = false;
		exprbegsys[i] = false;
		factbegsys[i] = false;
		boolbegsys[i] = false;
	}

	/* 设置声明开始符号集 */
	declbegsys[constsym] = true;
	declbegsys[intsym]   = true;
	declbegsys[boolsym]  = true;

	/* 设置语句开始符号集 */
	statbegsys[ifsym]    = true;
	statbegsys[whilesym] = true;
	statbegsys[writesym] = true;
	statbegsys[readsym]  = true;
	statbegsys[lbrace]   = true;	// compound_stat
	statbegsys[semicolon]= true;	// expression_stat
	statbegsys[ident]    = true;	// expression
	statbegsys[oddsym]	 = true;	// bool_expr
	statbegsys[notsym]   = true;	// bool_expr
	statbegsys[forsym]   = true;
	statbegsys[dosym] 	 = true;
	statbegsys[lparen]   = true;	// factor
	statbegsys[ident]    = true;
	statbegsys[number]   = true;
	statbegsys[truesym]  = true;	// bool_value
	statbegsys[falsesym] = true;

	/* 设置表达式开始符号集 */
	exprbegsys[ident]    = true;
	exprbegsys[oddsym]   = true;
	exprbegsys[notsym]   = true;
	exprbegsys[lparen]   = true;
	exprbegsys[number]   = true;
	exprbegsys[truesym]  = true;
	exprbegsys[falsesym] = true;

	/* 设置因子开始符号集 */
	factbegsys[lparen]   = true;
	factbegsys[ident]    = true;
	factbegsys[number]   = true;

	/* 设置布尔值开始符号集 */
	boolbegsys[ident]    = true;
	boolbegsys[truesym]  = true;
	boolbegsys[falsesym] = true;

	/* 设置出错信息提示 */
	emsg[1]  = "the equal sign must be followed by a number";
	emsg[2]  = "the equal sign must be followed by a boolean";
	emsg[3]  = "there must be an equal sign";
	emsg[4]  = "there must be an identifier";
	emsg[5]  = "missing a semicolon";
	emsg[6]  = "use ; rather than ,";
	emsg[7]  = "identifier undeclared";
	emsg[8]  = "missing a left parenthesis";
	emsg[9]  = "missing a right parenthesis";
	emsg[10] = "missing a left brace";
	emsg[11] = "missing a right brace";
	emsg[12] = "integer overflow";
	emsg[13] = "misplaced integer";
	emsg[14] = "misplaced boolean";
	emsg[15] = "identifier should not be constant";
	emsg[16] = "missing while";
	emsg[17] = "missing int/bool";
	emsg[18] = "waiting for a statement";
	emsg[19] = "expression cannot start with this symbol";
	emsg[20] = "wrong expression";
	emsg[21] = "program is incomplete";
	emsg[22] = "too many nesting levels";
	emsg[23] = "program is too long";
	emsg[24] = "displacement address is too big";

	/* 设置指令名称 */
	mnemonic[lit] = "lit";
	mnemonic[opr] = "opr";
	mnemonic[lod] = "lod";
	mnemonic[sto] = "sto";
	mnemonic[ini] = "ini";
	mnemonic[jmp] = "jmp";
	mnemonic[jpc] = "jpc";
}

/**
 * 用数组实现集合的集合运算
 */
int inset(int e, bool * s){
	return s[e];
}

int addset(bool * sr, bool * s1, bool * s2, int n){
	for ( int i = 0; i < n; ++ i ){
		sr[i] = s1[i] || s2[i];
	}
	return 0;
}

int subset(bool* sr, bool* s1, bool* s2, int n){
	for ( int i = 0; i < n; ++ i ){
		sr[i] = s1[i] && (!s2[i]);
	}
	return 0;
}

int mulset(bool* sr, bool* s1, bool* s2, int n){
	for ( int i = 0; i < n; ++ i ){
		sr[i] = s1[i] && s2[i];
	}
	return 0;
}


/**
 * 出错处理，打印出错位置和错误编码
 */
void error(int n){
#ifdef DEBUG_USE_ONLY
	cout << "Error " << n << ": " << emsg[n] << " around line " << lineno << endl;
#endif
	pout->append("Error "+to_string(n)+": "+emsg[n]+" around line "+to_string(lineno)+"\n");
	++ err;
	// 严重错误，直接退出
	if ( n == 21 || n == 22 || n == 23 || n == 24 ){
#ifndef DEBUG_USE_ONLY
        pthread_exit((void *)1234);
#else
		cout << * pout << endl;
		exit(0);
#endif
	}
	// 错误过多，直接退出
	if ( err > maxerr ){
		pout->append("Too many errors! (maxerr: " + to_string(maxerr) + ")\n");
#ifndef DEBUG_USE_ONLY
        pthread_exit((void *)1234);
#else
		cout << * pout << endl;
		exit(0);
#endif
	}
}

/**
 * 读取一个字符
 * 被getsym()调用
 */
void getch(){
	// 输入串已经读完了
    if ( inoff >= (int)pin->length() ){
		error(21);
        return;
	}
	ch = pin->at(inoff ++);
	if ( ch == '\n' )
		++ lineno;
}

/**
 * 词法分析，获取一个符号
 */
void getsym(){
	int i;
	// 过滤空格、换行符、制表符、注释
	while ( ch == ' ' || ch == '\n' || ch == '\t' || ch == '/' ){
        if ( ch != '/' )
            getch();
        else{
			getch();
			if ( ch == '*' ){	// 过滤注释
				i = 0;
				do{
					getch();	// 跳过注释，直到出现 */
					if ( i == 1 && ch != '/' ) 	// 上一个是*，这一个不是/
						i = 0;
					if ( ch == '*' )			// 这一个是*
						i = 1;
				}while ( i != 1 || ch != '/' );	// 没出现*/，继续循环
				getch();
			}else{				// 非注释，退出
				sym = slash;
				return;
			}
		}
	}
	// 标识符或保留字
	if ( ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ){
		a = "";	// 临时符号
		do {
			a += ch;
			getch();
		}while(('a'<=ch&&ch<='z')||('A'<=ch&&ch<='Z')||('0'<=ch&&ch<='9'));
		id = a;
		// 搜索判断是否是保留字
		for ( i = 0; i < norw; ++ i ){
			if ( id == word[i] ){
				sym = wsym[i];	// 保留字编号
#ifdef DEBUG_USE_ONLY
				cout << "norw: " << a << endl;
#endif
				break;
			}
		}
		if ( i == norw ){
			sym = ident;		// 不是保留字，是标识符
#ifdef DEBUG_USE_ONLY
			cout << "ident: " << a << endl;
#endif
		}
	}
	// 数字
	else if ( ('0' <= ch && ch <= '9') ){
		i = num = 0;
		sym = number;
		do {
			num = 10 * num + ch - '0';
			++ i;
			getch();
		}while ( ('0' <= ch && ch <= '9') );
		if ( i > nmax )	// 数字位数太多
			error(12);
#ifdef DEBUG_USE_ONLY
		cout << "number: " << num << endl;
#endif
	}
	// 双分界符、单分界符
	else{
		// 双分界符
		if ( ch == '>' ){
			getch();
			if ( ch == '=' ){
				sym = geq;		// >=
				getch();
			}else{
				sym = gtr;		// >
			}
		}else if ( ch == '<' ){
			getch();
			if ( ch == '=' ){
				sym = leq;		// <=
#ifdef DEBUG_USE_ONLY
				cout << "leq" << endl;
#endif
				getch();
			}else{
				sym = lss;		// <
			}
		}else if ( ch == '!' ){
			getch();
			if ( ch == '=' ){
				sym = neq;		// !=
				getch();
			}else{
				sym = excla;	// !
			}
		}else if ( ch == '=' ){
			getch();
			if ( ch == '=' ){
				sym = eql;		// ==
				getch();
			}else{
				sym = assign;	// =
#ifdef DEBUG_USE_ONLY
				cout << "assign" << endl;
#endif
			}
		}else if ( ch == '+' ){
			getch();
			if ( ch == '+' ){
				sym = incre;	// ++
				getch();
			}else{
				sym = plussym;	// +
			}
		}else if ( ch == '-' ){
			getch();
			if ( ch == '-' ){
				sym = decre;	// --
				getch();
			}else{
				sym = minussym;	// -
			}
		}
		// 单分界符或不能识别的符号
        else{
			sym = ssym[int(ch)];
            if ( ch == '{' )
				++ bracecnt;
            else if ( ch == '}' )
				-- bracecnt;
			if ( bracecnt != 0 )	// 程序还没结束
				getch();
		}
	}
}

/**
 * @brief       在符号表中加入一项
 * @param k		标识符的种类
 * @param ptx	符号表尾指针的指针，为了可以改变符号表尾指针的值
 */
void enter(enum object k, int * ptx, int lev, int * pdx){
	++ (* ptx);
	table[(* ptx)].name = id;
	table[(* ptx)].kind = k;
	switch ( k ){
		case constint:
			table[(* ptx)].val = num;
			break;
		case constbool:
			if ( sym == truesym )
				table[(* ptx)].val = 1;
			else
				table[(* ptx)].val = 0;
			break;
		case integer:
        case boolean:
			table[(* ptx)].level = lev;
			table[(* ptx)].adr = (* pdx);
			++ (* pdx);
			break;
	}
}

/**
 * 查找标识符在符号表中的位置，从tx开始倒序查找标识符
 * @param id	要查找的名字
 * @param tx	当前符号表尾指针
 * @return		找到则返回在符号表中的位置，否则返回0
 */
int position(string id, int tx){
	int i = tx;
	table[0].name = id;
	while ( table[i].name != id ){
		-- i;
	}
	return i;
}

/**
 * 测试当前符号是否合法
 * @brief 在语法分析程序的入口和出口处调用测试函数test，检查当前单词进入和退出该语法单位的合法性
 *
 * @param s1	需要的单词集合
 * @param s2	如果不是需要的单词，在某一出错状态时，可恢复语法分析继续正常工作的补充单词符号集合
 * @param n  	错误号
 */
void test(bool * s1, bool * s2, int n){
	if ( ! inset(sym, s1) ){
		error(n);
		// 当检测不通过时，不停获取符号，直到它属于需要的集合或补救的集合
		while ( ( ! inset(sym, s1) ) && ( ! inset(sym, s2) ) ){
			getsym();
		}
	}
}

/**
 * 生成目标代码
 */
void gen(enum fct x, int y, int z){
	if ( cx >= cxmax )			// 生成的虚拟机代码程序过长
		error(23);
    if ( x != lit && z >= amax )
		error(24);				// 地址偏移越界
	code[cx].f = x;
	code[cx].l = y;
	code[cx].a = z;
	++ cx;
}

/**
 * 通过过程基址求上 l 层过程的基址
 */
int base(int l, int * s, int b){
	int b1;
	b1 = b;
	while (l > 0){
		b1 = s[b1];
		-- l;
	}
	return b1;
}

/**
 * 将指令以字符串形式保存
 */
void listinstr(){
	* pinstr = "";
	for ( int i = 0; i < cx; ++ i ){
		pinstr->append(to_string(i)+" "+mnemonic[code[i].f]+" "+to_string(code[i].l)+", "+to_string(code[i].a)+"\n");
	}
}

/**
 * 将符号表以字符串形式保存
 */
void listtable(int tx){
    * ptable = "============ Symbol Table ============\n";
	// 符号表的第一行是主程序
	for ( int i = 1; i <= tx; ++ i ){
		switch ( table[i].kind ){
			case constint:
				ptable->append(table[i].name+" constint val = "+to_string(table[i].val)+"\n");
				break;
			case constbool:
				ptable->append(table[i].name+" constbool val = ");
				if ( table[i].val == 1 ){
					ptable->append("true\n");
				}else{
					ptable->append("false\n");
				}
				break;
			case integer:
				ptable->append(table[i].name+" integer level = "+to_string(table[i].level)+" adr = "+to_string(table[i].adr)+"\n");
				break;
            case boolean:
				ptable->append(table[i].name+" boolean level = "+to_string(table[i].level)+" adr = "+to_string(table[i].adr)+"\n");
				break;
			default:
				break;
		}
	}
    ptable->append("======================================\n");
}

/**
 * 编译程序主体
 * @param tx	符号表当前尾指针
 * @param fsys	当前模块的后继符号集合
 */
void program(int lev, int * ptx){
	// 传给下级函数的符号集合
	bool nxtlev[symnum];

	// 目标代码生成
	int dx;						// 记录数据分配的相对地址
	int tx0;					// 保留初始tx

	dx = 3;						// SL, DL, RA
	tx0 = * ptx;				// 本层标识符在符号表中的初始位置
	table[tx0].adr = cx;		// 记录跳转语句的地址，方便后续回填
	gen(jmp, 0, 0);				// 跳转位置待回填

	if ( lev > levmax ){
		error(22);				// 嵌套层数过多
	}

	// 检查FIRST
	if ( sym == lbrace ){
		getsym();
	}else{
		error(10);				// 丢了左花括号
		++ bracecnt;
	}

	// 常量、变量声明
	// FOLLOW(declaration_list) = FIRST(statement_list) U {'}'}
	memcpy(nxtlev, statbegsys);
	nxtlev[rbrace] = true;
	declaration_list(nxtlev, ptx, lev, &dx);

	// 声明完常量、变量后，回填
	code[table[tx0].adr].a = cx;// 回填jmp地址
	table[tx0].adr = cx;		// 回填符号表中主函数过程的adr
	table[tx0].size = dx;		// 回填符号表中主函数过程的size

	gen(ini, 0, dx);

	// FOLLOW(statement_list) = {'}'}
	memzro(nxtlev);
	nxtlev[rbrace] = true;
	statement_list(nxtlev, ptx, lev);

	// return
	gen(opr, 0, 0);

	if ( sym != rbrace ){
		error(11);				// 丢了右花括号
		-- bracecnt;
	}
}

/**
 * 声明列表处理
 */
void declaration_list(bool * fsys, int * ptx, int lev, int * pdx){
	bool nxtlev[symnum];

	// 在declaration_list里测试declaration_stat的FIRST和FOLLOW
	// 测试FIRST
	while ( inset(sym, declbegsys) ){			// 直到没有声明符号
		declaration_stat(ptx, lev, pdx);
	}
	// 测试FOLLOW
	memzro(nxtlev);								// 后继全都在fsys里了，没有其他补救集合
	test(fsys, nxtlev, 18);
}

/**
 * 声明行处理
 */
void declaration_stat(int * ptx, int lev, int * pdx){
    string constID;
	// 在declaration_list里测试FIRST和FOLLOW
	if ( sym == constsym ){
		getsym();
		// const int
		if ( sym == intsym ){
			getsym();
			if ( sym == ident ){
                getsym();
            }else{
                error(4);               // 这里必须是标识符
            }
            if ( sym == assign ){
                getsym();               // 获取 number
            }else{
                error(3);               // 这里必须是 =
            }
            if ( sym == number ){
                enter(constint, ptx, lev, pdx);
            }else{
                error(1);               // = 后面跟数
            }
            getsym();
            if ( sym == semicolon ){
                getsym();
            }else if ( sym == comma ){
                getsym();
                error(6);               // 要用;而不是,
            }else{
                error(5);               // 丢分号
            }
		}
		// const bool
        else if ( sym == boolsym ){
			getsym();
			if ( sym == ident ){
                constID = id;           // 记录const bool的ID
				getsym();
            }else{
                error(4);				// 这里必须是标识符
            }
            if ( sym == assign ){
                getsym();               // 获取 true/false
            }else{
                error(3);               // 这里必须是 =
            }
            if ( sym == truesym || sym == falsesym ){
                id = constID;
                enter(constbool, ptx, lev, pdx);
            }else{
                error(2);               // = 后面跟true/false
            }
            getsym();
            if ( sym == semicolon ){
                getsym();
            }else if ( sym == comma ){
                getsym();
                error(6);               // 要用;而不是,
            }else{
                error(5);               // 丢分号
            }
		}else{
			error(17);					// 等待类型保留字
		}
	}else if ( sym == intsym ){
		getsym();
		if ( sym == ident ){
			enter(integer, ptx, lev, pdx);
			getsym();					// ;
			if ( sym == semicolon ){
				getsym();
			}else if ( sym == comma ){
				getsym();
				error(6);				// 要用;而不是,
			}else{
				error(5);				// 丢分号
			}
		}else{
			error(4);					// int后应是标识符
		}
	}else if ( sym == boolsym ){
		getsym();
		if ( sym == ident ){
            enter(boolean, ptx, lev, pdx);
			getsym();					// ;
			if ( sym == semicolon ){
				getsym();
			}else if ( sym == comma ){
				getsym();
				error(6);				// 要用;而不是,
			}else{
				error(5);				// 丢分号
			}
		}else{
			error(4);					// bool后应是标识符
		}
	}
}

/**
 * 语句列表处理
 */
void statement_list(bool * fsys, int * ptx, int lev){
	bool nxtlev[symnum];
	
	// 每个后继符号集合都包含上层后继符号集合，以便补救
	// FOLLOW(statement) = {'}'} U FIRST(statement)
	addset(nxtlev, fsys, statbegsys, symnum);

	// 测试FIRST
	while ( inset(sym, statbegsys) ){			// 直到没有语句的FIRST符号
		statement(nxtlev, ptx, lev);
	}
	// 测试FOLLOW
	memzro(nxtlev);								// 后继全都在fsys里了，没有其他补救集合
    test(fsys, nxtlev, 11);                     // statement_list后面应该是终结右花括号
}

/**
 * 语句处理
 */
void statement(bool * fsys, int * ptx, int lev){
	bool nxtlev[symnum];
	memcpy(nxtlev, fsys);						// 每个后继符号集合都包含上层后继符号集合，以便补救
	// 在statement_list里已经测试过FIRST
	if ( sym == ifsym ){
		if_stat(nxtlev, ptx, lev);
	}else if ( sym == whilesym ){
		while_stat(nxtlev, ptx, lev);
	}else if ( sym == writesym ){
		write_stat(nxtlev, ptx, lev);
	}else if ( sym == readsym ){
		read_stat(nxtlev, ptx, lev);
	}else if ( sym == lbrace ){
		compound_stat(nxtlev, ptx, lev);
	}else if ( sym == forsym ){
		for_stat(nxtlev, ptx, lev);
	}else if ( sym == dosym ){
		dowhile_stat(nxtlev, ptx, lev);
	}else{
		expression_stat(nxtlev, ptx, lev);
	}
	// 测试FOLLOW
	memzro(nxtlev);
	test(fsys, nxtlev, 18);						// 这里等待一条语句
}

/**
 * if语句处理
 * 1. IF-ELSE ***************
 * 		T(expression)
 * 		jpc 0, L1		// no, goto else statement
 * 		T(statement)	// if statement
 * 		jmp 0, Lend
 * L1:	T(statement)	// else statement
 * Lend:
 * 2. IF ********************
 * 		T(expression)
 * 		jpc 0, L1
 * 		T(statement)
 * L1:
 */
void if_stat(bool * fsys, int * ptx, int lev){
	bool nxtlev[symnum];
	int cx1, cx2;					// 记录待回填的指令地址

	getsym();

	if ( sym == lparen ){
		getsym();
	}else{
		error(8);					// 丢了左括号(
	}

	memcpy(nxtlev, fsys);
    nxtlev[rparen] = true;
    expression(nxtlev, ptx, lev);	// 调用条件处理

	if ( sym == rparen ){
		getsym();
	}else{
		error(9);					// 丢了右括号)
	}
	
	cx1 = cx;						// 保存当前指令地址
	gen(jpc, 0, 0);					// 跳转到else/end【回填】

	memcpy(nxtlev, fsys);
	nxtlev[elsesym] = true;
	statement(nxtlev, ptx, lev);	// 处理if条件后的语句

	if ( sym == elsesym ){			// 1. IF-ELSE 语句
		cx2 = cx;
		gen(jmp, 0, 0);				// 跳转到end【回填】
		code[cx1].a = cx;			// 回填else

		getsym();
		statement(fsys, ptx, lev);	// 处理else后的statement
		code[cx2].a = cx;			// 回填end
	}else{							// 2. IF 语句
		code[cx1].a = cx;
	}
	// 在statement里测试FOLLOW
}

/**
 * while语句处理
 * L1:	T(expression)
 * 		jpc 0, L2
 * 		T(statement)
 * 		jmp 0, L1
 * L2:
 */
void while_stat(bool * fsys, int * ptx, int lev){
	bool nxtlev[symnum];
	int L1, cx0;					// 记录待回填的指令地址

	getsym();
	if ( sym == lparen ){
		getsym();
	}else{
		error(8);					// 丢了左括号(
	}

	L1 = cx;						// 记录L1的地址
	memcpy(nxtlev, fsys);
    nxtlev[rparen] = true;
    expression(nxtlev, ptx, lev);	// 调用条件处理

	cx0 = cx;
	gen(jpc, 0, 0);					// 跳出循环【回填】
	
	if ( sym == rparen ){
		getsym();
	}else{
		error(9);					// 丢了右括号)
	}

	statement(fsys, ptx, lev);		// 处理while循环体

	gen(jmp, 0, L1);				// 跳回循环
	code[cx0].a = cx;
}

/**
 * write语句处理
 * 		T(expression)
 * 		opr 0, 20			// write
 * 		opr 0, 21			// 换行
 */
void write_stat(bool * fsys, int * ptx, int lev){
	bool nxtlev[symnum];
	getsym();
	if ( sym == lparen ){
		getsym();
	}else{
		error(8);					// 丢了左括号(
	}

	memcpy(nxtlev, fsys);
	nxtlev[rparen] = true;
//    isCondition = 1;
	expression(nxtlev, ptx, lev);	// 调用条件处理
//    isCondition = 0;

	gen(opr, 0, 20);
	gen(opr, 0, 21);

	if ( sym == rparen ){
		getsym();
	}else{
		error(9);					// 丢了右括号)
	}

	if ( sym == semicolon ){
		getsym();
	}else{
		error(5);					// 丢了一个分号
	}
}

/**
 * read语句处理：read ID;
 * 		opr 0, 22			// read
 * 		sto lev-level, adr	// store
 */
void read_stat(bool * fsys, int * ptx, int lev){
	int i;
	getsym();
	if ( sym == ident ){
		i = position(id, *ptx);		// 查找标识符在符号表中的位置
		if ( i == 0 ){
			error(7);				// 标识符未声明
		}else{
			gen(opr, 0, 22);		// 读取值到栈顶
			gen(sto, lev-table[i].level, table[i].adr);
		}
		getsym();					// ;
		if ( sym == semicolon ){
			getsym();
		}else{
			error(5);				// 丢了一个分号
		}
	}else{
		error(4);					// 丢了一个标识符

		if ( sym == semicolon ){
			getsym();
		}else{
			error(5);				// 丢了一个分号
		}
	}
}

/**
 * 复合语句处理
 * 		T(statement_list)
 */
void compound_stat(bool * fsys, int * ptx, int lev){
	bool nxtlev[symnum];
	getsym();

	memcpy(nxtlev, fsys);
	nxtlev[rbrace] = true;
	statement_list(nxtlev, ptx, lev);
	
	if ( sym == rbrace ){
		getsym();
	}else{
		error(11);					// 丢了右括号}
		-- bracecnt;
	}
}

/**
 * 表达式语句处理
 * 		T(expression)
 * 		opr 0, 23		// pop
 */
void expression_stat(bool * fsys, int * ptx, int lev){
	bool nxtlev[symnum];
	if ( inset(sym, exprbegsys) ){	// expression;
		memcpy(nxtlev, fsys);
		nxtlev[semicolon] = true;
		expression(nxtlev, ptx, lev);
	}
	if ( sym == semicolon ){
		getsym();
	}else{
		error(5);					// 漏分号
	}
    gen(opr, 0, 23);                // 弹出表达式的值
}

/**
 * 表达式处理
 * 1. ID = <bool_expr> ******
 * 		T(bool_expr)
 * 		sto lev-level, adr
 * 		lod ID				// 留ID的值在栈顶
 * 2. <bool_expr> ***********
 * 		T(bool_expr)
 */
void expression(bool * fsys, int * ptx, int lev){
	int i;
	// 可能包含赋值
	if ( sym == ident ){
		i = position(id, *ptx);
		if ( i == 0 ){
			error(7);					// 标识符未声明
			do{							// 直接跳过这个expression
				getsym();
			}while( ! inset(sym, fsys) );
//            qDebug("in expression sym = %d", sym);
			return;
		}
		getsym();						// 判断是不是=
		if ( sym == assign ){			// 1. ID = <bool_expr>
			getsym();
			bool_expr(fsys, ptx, lev);
			gen(sto, lev-table[i].level, table[i].adr);
            // expression需要留一个返回值在栈顶
            if ( table[i].kind == constint || table[i].kind == constbool )
                error(15);              // 不可以给常量赋值
            else
                gen(lod, lev-table[i].level, table[i].adr);
		}else{							// 2. <bool_expr>
			bool_expr(fsys, ptx, lev, i);	// 把预取的ID传进去
		}
	// 不包含赋值
	}else{
		bool_expr(fsys, ptx, lev);
	}
}

/**
 * 布尔表达式处理
 * 1. 预取
 * 1.1. ID { relop [not] <bool_value> }
 * 		lod ID / lit ID
 * 		{ T(bool_value)
 * 		  [ opr 0, 19 ]		// not
 * 		  opr 0, relop  }
 * 1.2. <additive_expr> [ relop <additive_expr> ]
 * 		T(additive_expr) with prei
 * 		[ T(additive_expr)
 * 		  opr 0, relop     ]
 * 2. 无预取
 * 2.1. odd expression
 * 		T(expression)
 * 		opr 0, 6			// odd
 * 2.2. [not] <bool_value> { relop [not] <bool_value> }
 * 		T(bool_value)
 * 		[ opr 0, 19 ]
 * 		{ T(bool_value)
 * 		  [ opr 0, 19 ]
 *        opr 0, relop  }
 * 2.3. <additive_expr> [ relop <additive_expr> ]
 * 		T(additive_expr)
 * 		[ T(additive_expr) 
 * 		  opr 0, relop     ]
 */
void bool_expr(bool * fsys, int * ptx, int lev, int prei){
	int i;
	bool nxtlev[symnum];
	enum symbol relop;					// 记录运算符
	// 1. 已经预取了一个ID
	if ( prei != 0 ){
		// bool_value(ptx); OR additive_expr(ptx): 根据ID的类型判断
		// 1.1. bool_value__ID
        if ( table[prei].kind == boolean || table[prei].kind == constbool ){

            if ( table[prei].kind == boolean ){
				gen(lod, lev-table[prei].level, table[prei].adr);
			}else{
				gen(lit, 0, table[prei].val);
			}

			// 当前sym是ID后的一个符号了
			while ( sym == andsym || sym == orsym ){
				relop = sym;
				getsym();

				memcpy(nxtlev, fsys);
				nxtlev[andsym] = true;
				nxtlev[orsym]  = true;
				
				if ( sym == notsym ){
					getsym();
					bool_value(nxtlev, ptx, lev);
					gen(opr, 0, 19);
				}else{
					bool_value(nxtlev, ptx, lev);
				}
				switch ( relop ){
					case andsym:
						gen(opr, 0, 17);	// and
						break;
					case orsym:
						gen(opr, 0, 18);	// or
						break;
					default:
						break;
				}
			}
		}
		// 1.2. additive_expr__ID
		else{
			memcpy(nxtlev, fsys);
			nxtlev[gtr] = true;
			nxtlev[lss] = true;
			nxtlev[geq] = true;
			nxtlev[leq] = true;
			nxtlev[eql] = true;
			nxtlev[neq] = true;
			additive_expr(nxtlev, ptx, lev, prei);	// 预取
			if ( sym == gtr || sym == lss || sym == geq || sym == leq || sym == eql || sym == neq ){
				relop = sym;
				getsym();
				additive_expr(fsys, ptx, lev);
				switch ( relop ){
					case gtr:
						gen(opr, 0, 12); break;
					case lss:
						gen(opr, 0, 10); break;
					case geq:
						gen(opr, 0, 11); break;
					case leq:
						gen(opr, 0, 13); break;
					case eql:
						gen(opr, 0, 8);  break;
					case neq:
						gen(opr, 0, 9);  break;
					default: break;
				}
			}
		}
	// 2. 没有预取ID，正常
	}else{
		// 2.1. odd expression
		if ( sym == oddsym ){
			getsym();
			expression(fsys, ptx, lev);
			gen(opr, 0, 6);
		}
		// 2.2. not <bool_value> { relop [not] <bool_value> }
		else if ( sym == notsym || sym == truesym || sym == falsesym ){
			goto LBool;
		}
		// 2.3. ID
		else if ( sym == ident ){
			i = position(id, *ptx);
			if ( i == 0 ){
				error(7);				// 标识符未声明
				do {					// 直接跳过这个bool_expr
					getsym();
				}while ( ! inset(sym, fsys) );
				return;
			}else{
                if ( table[i].kind == boolean || table[i].kind == constbool ){
					goto LBool;
				}else{
					goto LAdditive;
				}
			}
		}
		// 3.1. additive_expr opr additive_expr
		else{
			goto LAdditive;
		}
	}
	return;
LBool:
	memcpy(nxtlev, fsys);
	nxtlev[andsym] = true;
	nxtlev[orsym]  = true;

	if ( sym == notsym ){
		getsym();
		bool_value(nxtlev, ptx, lev);
		gen(opr, 0, 19);
	}else{
		bool_value(nxtlev, ptx, lev);
	}

	while ( sym == andsym || sym == orsym ){
		relop = sym;
		getsym();
		if ( sym == notsym ){
			getsym();
			bool_value(nxtlev, ptx, lev);
			gen(opr, 0, 19);
		}else{
			bool_value(nxtlev, ptx, lev);
		}
		switch ( relop ){
			case andsym:
				gen(opr, 0, 17);	// and
				break;
			case orsym:
				gen(opr, 0, 18);	// or
				break;
			default: break;
		}
	}
	return;
LAdditive:
	memcpy(nxtlev, fsys);
	nxtlev[gtr] = true;
	nxtlev[lss] = true;
	nxtlev[geq] = true;
	nxtlev[leq] = true;
	nxtlev[eql] = true;
	nxtlev[neq] = true;
	additive_expr(nxtlev, ptx, lev);
	if ( sym == gtr || sym == lss || sym == geq || sym == leq || sym == eql || sym == neq ){
		relop = sym;
		getsym();
		additive_expr(fsys, ptx, lev);
		switch ( relop ){
			case gtr:
				gen(opr, 0, 12); break;
			case lss:
				gen(opr, 0, 10); break;
			case geq:
				gen(opr, 0, 11); break;
			case leq:
				gen(opr, 0, 13); break;
			case eql:
				gen(opr, 0, 8);  break;
			case neq:
				gen(opr, 0, 9);  break;
			default: break;
		}
	}
	return;
}


/**
 * 加法表达式处理：<term1> [ relop <term2> ]
 * 		T(term1)
 * 		[ T(term2)
 * 		  gen(opr 0, relop) ]
 */
void additive_expr(bool * fsys, int * ptx, int lev, int prei){
	bool nxtlev[symnum];
	enum symbol relop;

	memcpy(nxtlev, fsys);
	nxtlev[plussym]  = true;
	nxtlev[minussym] = true;
	nxtlev[xorsym]   = true;
	term(nxtlev, ptx, lev, prei);
	while ( sym == plussym || sym == minussym || sym == xorsym ){
		relop = sym;
		getsym();
		term(nxtlev, ptx, lev);
		switch ( relop ){
			case plussym:
				gen(opr, 0, 2);	 break;
			case minussym:
				gen(opr, 0, 3);  break;
			case xorsym:
				gen(opr, 0, 16); break;
			default: break;
		}
	}
}

/**
 * 项处理：<factor1> [ relop <factor2> ]
 * 		T(factor1)
 * 		[ T(factor2)
 * 		  gen(opr 0, relop) ]
 */
void term(bool * fsys, int * ptx, int lev, int prei){
	bool nxtlev[symnum];
	enum symbol relop;

	memcpy(nxtlev, fsys);
	nxtlev[times]   = true;
	nxtlev[slash]   = true;
	nxtlev[percent] = true;
	factor(nxtlev, ptx, lev, prei);
	while ( sym == times || sym == slash || sym == percent ){
		relop = sym;
		getsym();
		factor(nxtlev, ptx, lev);
		switch ( relop ){
			case times:
				gen(opr, 0, 4);	break;
			case slash:
				gen(opr, 0, 5); break;
			case percent:
				gen(opr, 0, 1); break;
			default: break;
		}
	}
}

/**
 * 因子处理
 * 1. 预取 ID [++/--]
 * 		lod ID / lit ID.val
 * 		[ lod ID		// 压入ID的旧值
 *        lit 0, 1
 * 		  opr 0, 2/3
 * 		  sto ID     ]
 * 2. 无预取
 * 2.1. ID [++/--]
 * 2.2. NUM
 * 		lit 0, NUM
 * 2.3. ( expression )
 * 		T(expression)
 */
void factor(bool * fsys, int * ptx, int lev, int prei){
	int i;
	bool nxtlev[symnum];

	// 已经预取了一个ID，类型肯定是integer或constint
	if ( prei != 0 ){					
		switch ( table[prei].kind ){
			case constint:
				gen(lit, 0, table[prei].val); break;
			case integer:
				gen(lod, lev-table[prei].level, table[prei].adr); break;
			default: break;
		}
		if ( sym == incre || sym == decre ){
			if ( table[prei].kind == constint ){
				error(15);				// 表达式不应该是const
			}else{
//                if ( isCondition )      // 表达式作为条件控制语句，需要留一个值
                // factor需要留一个返回值
                gen(lod, lev-table[prei].level, table[prei].adr);
				gen(lit, 0, 1);
				if ( sym == incre )
					gen(opr, 0, 2);
				else
					gen(opr, 0, 3);
				gen(sto, lev-table[prei].level, table[prei].adr);
			}
			getsym();
		}
	}
	// 无预取
	else{
		test(factbegsys, fsys, 19);		// 测试FIRST
		// ID
		if ( sym == ident ){
			i = position(id, *ptx);
			if ( i == 0 ){
				error(7);				// 标识符未声明
				do {					// 直接跳过这个bool_expr
					getsym();
				}while ( ! inset(sym, fsys) );
				return;
			}
            else if ( table[i].kind == boolean || table[i].kind == constbool ){
				error(14);				// 表达式里不应该有bool数据
			}
			else{
				switch ( table[i].kind ){
					case constint:
						gen(lit, 0, table[i].val); break;
					case integer:
						gen(lod, lev-table[i].level, table[i].adr); break;
					default: break;
				}
			}
			getsym();
			if ( sym == incre || sym == decre ){
				if ( table[i].kind == constint ){
					error(15);			// 表达式不应该是const
				}else{
//                    if ( isCondition )  // 表达式作为条件控制语句，需要留一个值
                    // factor留一个返回值
                    gen(lod, lev-table[prei].level, table[prei].adr);
					gen(lit, 0, 1);
					if ( sym == incre )
						gen(opr, 0, 2);
					else
						gen(opr, 0, 3);
					gen(sto, lev-table[i].level, table[i].adr);
				}
				getsym();
			}
		}
		// NUM
		else if ( sym == number ){
			gen(lit, 0, num);
			getsym();
		}
		// ( expression )
		else{
			if ( sym == lparen ){
				getsym();
			}else{
				error(8);				// 缺少左括号
			}
			memcpy(nxtlev, fsys);
			nxtlev[rparen] = true;
			expression(nxtlev, ptx, lev);
			if ( sym == rparen ){
				getsym();
			}else{
				error(9);				// 丢了右括号)
			}
		}
	}
	memzro(nxtlev);
	test(fsys, nxtlev, 20);
}

/**
 * 布尔值处理：ID/true/false
 * 		lod ID / lit true|false
 */
void bool_value(bool * fsys, int * ptx, int lev){
	int i;
	bool nxtlev[symnum];
	test(boolbegsys, fsys, 19);
	// ID, true, false
	if ( sym == ident ){
		i = position(id, *ptx);
		if ( i == 0 ){
			error(7);					// 标识符未声明
		}else{
			switch ( table[i].kind ){
				case constbool:
					gen(lit, 0, table[i].val); break;
                case boolean:
					gen(lod, lev-table[i].level, table[i].adr); break;
				default:
					error(13); break;	// 表达式里不应该有int数据
			}
		}
		getsym();
	}else if ( sym == truesym || sym == falsesym ){
		if ( sym == truesym )
			gen(lit, 0, 1);
		else
			gen(lit, 0, 0);
		getsym();
	}
	memzro(nxtlev);
	test(fsys, nxtlev, 20);
}

/**
 * for循环处理：for ( [ <expression1> ] ; [ <bool_expr> ] ; [ <expression2> ] ) <statement>
 * 		[ T(expression1) ]
 * L1:	[ T(bool_expr) ]
 * 		jpc 0, Lend		// 假出口
 * 		jmp 0, L3		// 真出口
 * L2:	[ T(expression2) ]
 * 		jmp 0, L1
 * L3:	T(statement)
 * 		jmp 0, L2
 * Lend:
 */
void for_stat(bool * fsys, int * ptx, int lev){
	bool nxtlev[symnum];
	int L1, L2, cx0;

	getsym();
	if ( sym == lparen ){
		getsym();
	}else{
		error(8);						// 丢了左括号
	}

	// for 第一块
	if ( inset(sym, exprbegsys) ){
		memcpy(nxtlev, fsys);
		nxtlev[semicolon] = true;
		expression(nxtlev, ptx, lev);
        gen(opr, 0, 23);                // 不需要表达式的返回值，pop
	}

	if ( sym == semicolon ){
		getsym();
	}else if ( sym == comma ){
		getsym();
		error(6);
	}else{
		error(5);						// 丢了分号
	}

	// for 第二块
	L1 = cx;							// 保存<bool_expr>入口地址
	if ( inset(sym, exprbegsys) ){		// case 1：FIRST(bool_expr)=FIRST(expression)
		memcpy(nxtlev, fsys);
		nxtlev[semicolon] = true;
		bool_expr(nxtlev, ptx, lev);
	}else{								// case 2：<bool_expr>为空
		gen(lit, 0, 1);					// 条件永远为真，死循环
	}
	cx0 = cx;
	gen(jpc, 0, 0);						// 假出口【回填】
	gen(jmp, 0, 0);						// 真出口【回填】
	
	if ( sym == semicolon ){
		getsym();
	}else if ( sym == comma ){
		getsym();
		error(6);
	}else{
		error(5);						// 丢了分号
	}

	// for 第三块
	L2 = cx;							// 保存<expression2>入口地址
	if ( inset(sym, exprbegsys) ){
		memcpy(nxtlev, fsys);
		nxtlev[rparen] = true;
		expression(nxtlev, ptx, lev);
        gen(opr, 0, 23);                // 不需要表达式的返回值，pop
	}
	gen(jmp, 0, L1);

	if ( sym == rparen ){
		getsym();
	}else{
		error(9);						// 丢了右括号)
	}

	// <statement>
	code[cx0+1].a = cx;					// 回填真出口
	statement(fsys, ptx, lev);
	gen(jmp, 0, L2);

	code[cx0].a = cx;					// 回填假出口
}

/**
 * do-while循环处理：do <statement> while ( <expression> );
 * L1:	T(statement)
 * 		T(expression)
 * 		jpc 0, Lend
 * 		jmp 0, L1
 * Lend:
 */
void dowhile_stat(bool * fsys, int * ptx, int lev){
	bool nxtlev[symnum];
	int L1, cx0;

	getsym();

	L1 = cx;

	memcpy(nxtlev, fsys);
	nxtlev[whilesym] = true;
    statement(nxtlev, ptx, lev);

	if ( sym == whilesym ){
		getsym();
	}else{
		error(16);						// 这里等待"while"
	}

	if ( sym == lparen ){
		getsym();
	}else{
		error(8);						// 丢了左括号
	}

	memcpy(nxtlev, fsys);
	nxtlev[rparen] = true;
	expression(nxtlev, ptx, lev);

	cx0 = cx;
	gen(jpc, 0, 0);						// 出口【回填】
	gen(jmp, 0, L1);					// 回到循环
	code[cx0].a = cx;					// 回填出口

	if ( sym == rparen ){
		getsym();
	}else{
		error(9);						// 丢了右括号)
	}

	if ( sym == semicolon ){
		getsym();
	}else{
		error(5);						// 丢了一个分号
	}
}

/**
 * @brief 输出数据栈内容
 * @param s     stack
 * @param top   stack top
 */
void liststack(int * s, int top){
    pstack->append("=============== Stack ===============\n");
    for ( int i = 1; i <= top; ++ i ){
        pstack->append(to_string(i)+"\t\t"+to_string(s[i])+"\n");
    }
    pstack->append("=====================================\n");
}

/**
 * 解释执行程序
 */
void interpret(string * pres_){
    pres = pres_;
    * pres = "";

    p = 0;
    b = 1;
    t = 0;
    memset(s, 0, sizeof(s));

	do {
		i = code[p];					// 取指
		p = p + 1;
		switch ( i.f ){
			case lit:
				t = t + 1;
				s[t] = i.a;
				break;
			case opr:
				switch ( i.a ){
					case 0:				// return
						t = b - 1;
						p = s[t + 3];
						b = s[t + 2];
						break;
					case 1:				// 取模
						t = t - 1;
						s[t] = s[t] % s[t + 1];
						break;
					case 2:				// 次栈顶项加上栈顶项
						t = t - 1;
						s[t] = s[t] + s[t + 1];
						break;
					case 3:				// 次栈顶项减去栈顶项
						t = t - 1;
						s[t] = s[t] - s[t + 1];
						break;
					case 4:				// 次栈顶项乘以栈顶项
						t = t - 1;
						s[t] = s[t] * s[t + 1];
						break;
					case 5:				// 次栈顶项除以栈顶项
						t = t - 1;
						s[t] = s[t] / s[t + 1];
						break;
					case 6:				// 栈顶元素的奇偶判断
						s[t] = s[t] % 2;
						break;
					case 8:				// 次栈顶项与栈顶项是否相等
						t = t - 1;
						s[t] = (s[t] == s[t + 1]);
						break;
					case 9:				// 次栈顶项与栈顶项是否不等
						t = t - 1;
						s[t] = (s[t] != s[t + 1]);
						break;
					case 10:			// 次栈顶项是否小于栈顶项
						t = t - 1;
						s[t] = (s[t] < s[t + 1]);
						break;
					case 11:			// 次栈顶项是否大于等于栈顶项
						t = t - 1;
						s[t] = (s[t] >= s[t + 1]);
						break;
					case 12:			// 次栈顶项是否大于栈顶项
						t = t - 1;
						s[t] = (s[t] > s[t + 1]);
						break;
					case 13: 			// 次栈顶项是否小于等于栈顶项
						t = t - 1;
						s[t] = (s[t] <= s[t + 1]);
						break;
					case 16:			// xor
						t = t - 1;
						s[t] = (s[t] ^ s[t + 1]);
						break;
					case 17:			// and
						t = t - 1;
						s[t] = (s[t] && s[t + 1]);
						break;
					case 18:			// or
						t = t - 1;
						s[t] = (s[t] || s[t + 1]);
						break;
					case 19:			// not
						s[t] = (! s[t]);
						break;
					case 20:			// write
						pres->append(to_string(s[t]));
						t = t - 1;
						break;
					case 21:			// 换行
						pres->append("\n");
						break;
                    case 22:			// read
                        t = t + 1;
                        sem_post(&readdata);    // 控制权移交给GUI去读数据
                        sem_wait(&dataready);   // 数据读完了返回解释线程
                        s[t] = indata;          // 读到栈顶
                        break;
                    case 23:            // pop
                        t = t - 1;
                        break;
				}
				break;
			case lod:
				t = t + 1;
				s[t] = s[base(i.l, s, b) + i.a];
				break;
			case sto:
				s[base(i.l, s, b) + i.a] = s[t];
				t = t - 1;
				break;
			case ini:
				t = t + i.a;
				break;
			case jmp:
				p = i.a;
				break;
			case jpc:
				if ( s[t] == 0 )
					p = i.a;
				t = t - 1;
				break;
			default:
				break;
		}
    }while ( p != 0 );

    isComplete = 1;             // 标记解释程序结束
    sem_post(&readdata);        // 控制权移交给GUI
}

/**
 * @brief 单步解释执行程序
 * @param pres_     输出结果
 * @param pstack_   输出数据栈
 */
void interpret_by_step(string * pres_, string * pstack_){
    pres = pres_;
    pstack = pstack_;

    if ( p == 0 ){
        b = 1;
        t = 0;
        memset(s, 0, sizeof(s));// 复原stack
    }

    * pstack = "p: " + to_string(p) + "\n";
    pstack->append("b: " + to_string(b) + "\n");

    i = code[p];
    p = p + 1;

    switch ( i.f ){
        case lit:
            t = t + 1;
            s[t] = i.a;
            break;
        case opr:
            switch ( i.a ){
                case 0:				// return
                    t = b - 1;
                    p = s[t + 3];
                    b = s[t + 2];
                    break;
                case 1:				// 取模
                    t = t - 1;
                    s[t] = s[t] % s[t + 1];
                    break;
                case 2:				// 次栈顶项加上栈顶项
                    t = t - 1;
                    s[t] = s[t] + s[t + 1];
                    break;
                case 3:				// 次栈顶项减去栈顶项
                    t = t - 1;
                    s[t] = s[t] - s[t + 1];
                    break;
                case 4:				// 次栈顶项乘以栈顶项
                    t = t - 1;
                    s[t] = s[t] * s[t + 1];
                    break;
                case 5:				// 次栈顶项除以栈顶项
                    t = t - 1;
                    s[t] = s[t] / s[t + 1];
                    break;
                case 6:				// 栈顶元素的奇偶判断
                    s[t] = s[t] % 2;
                    break;
                case 8:				// 次栈顶项与栈顶项是否相等
                    t = t - 1;
                    s[t] = (s[t] == s[t + 1]);
                    break;
                case 9:				// 次栈顶项与栈顶项是否不等
                    t = t - 1;
                    s[t] = (s[t] != s[t + 1]);
                    break;
                case 10:			// 次栈顶项是否小于栈顶项
                    t = t - 1;
                    s[t] = (s[t] < s[t + 1]);
                    break;
                case 11:			// 次栈顶项是否大于等于栈顶项
                    t = t - 1;
                    s[t] = (s[t] >= s[t + 1]);
                    break;
                case 12:			// 次栈顶项是否大于栈顶项
                    t = t - 1;
                    s[t] = (s[t] > s[t + 1]);
                    break;
                case 13: 			// 次栈顶项是否小于等于栈顶项
                    t = t - 1;
                    s[t] = (s[t] <= s[t + 1]);
                    break;
                case 16:			// xor
                    t = t - 1;
                    s[t] = (s[t] ^ s[t + 1]);
                    break;
                case 17:			// and
                    t = t - 1;
                    s[t] = (s[t] && s[t + 1]);
                    break;
                case 18:			// or
                    t = t - 1;
                    s[t] = (s[t] || s[t + 1]);
                    break;
                case 19:			// not
                    s[t] = (! s[t]);
                    break;
                case 20:			// write
                    pres->append(to_string(s[t]));
                    t = t - 1;
                    break;
                case 21:			// 换行
                    pres->append("\n");
                    break;
                case 22:			// read
                    t = t + 1;
                    sem_post(&readdata);    // 控制权移交给GUI去读数据
                    sem_wait(&dataready);   // 数据读完了返回解释线程
                    s[t] = indata;          // 读到栈顶
                    break;
                case 23:            // pop
                    t = t - 1;
                    break;
            }
            break;
        case lod:
            t = t + 1;
            s[t] = s[base(i.l, s, b) + i.a];
            break;
        case sto:
            s[base(i.l, s, b) + i.a] = s[t];
            t = t - 1;
            break;
        case ini:
            t = t + i.a;
            break;
        case jmp:
            p = i.a;
            break;
        case jpc:
            if ( s[t] == 0 )
                p = i.a;
            t = t - 1;
            break;
        default:
            break;
    }
    liststack(s, t);

    isComplete = 1;             // 标记解释程序结束
    sem_post(&readdata);        // 控制权移交给GUI
}
